import { config } from '@/try-on/config'
import {
  Group,
  Material,
  Mesh,
  OrthographicCamera,
  Plane,
  Raycaster,
  Vector2,
  Vector3,
} from 'three'

export class Contrast {
  enable = config.enableContrast
  clipPlane = new Plane()
  canvas: HTMLCanvasElement
  container: HTMLDivElement
  group?: Group
  raycaster = new Raycaster()
  mouse = new Vector2()
  dragging = false
  loaded = false
  camera: OrthographicCamera
  divider = document.getElementById('divider') as HTMLDivElement
  constructor(canvas: HTMLCanvasElement, camera: OrthographicCamera) {
    this.canvas = canvas
    this.camera = camera
    this.container = canvas.parentElement as HTMLDivElement
  }
  upMaterial(group: Group) {
    this.group = group
    if (!this.enable) return
    group.traverse((object) => {
      if (object instanceof Mesh && object.material instanceof Material) {
        object.material.clippingPlanes = [this.clipPlane]
      }
    })
    const { width } = this.container.getBoundingClientRect()
    this.updatePlaneClip(width / 2)
    if (!this.loaded) this.init()
    this.divider.style.display = ''
    this.divider.style.left = '50%'
  }
  init() {
    this.container.addEventListener('mousedown', () => (this.dragging = true))
    this.container.addEventListener('touchstart', () => (this.dragging = true))
    this.container.addEventListener('touchmove', this.onMove.bind(this))
    this.container.addEventListener('mousemove', this.onMove.bind(this))
    window.addEventListener('mouseup', () => (this.dragging = false))
    window.addEventListener('touchend', () => (this.dragging = false))
  }
  onMove(e: MouseEvent | TouchEvent) {
    let clientX = 0
    if (e instanceof MouseEvent) {
      clientX = e.clientX
    } else {
      clientX = e.touches[0].clientX
    }
    if (this.dragging) {
      const rect = this.container.getBoundingClientRect()
      const x = Math.max(0, Math.min(rect.width, clientX - rect.left))
      this.divider.style.left = `${x}px`
      this.updatePlaneClip(x)
    }
  }
  enableClip() {
    this.enable = true
    if (this.group) {
      this.divider.style.display = ''
      this.divider.style.left = '50%'
      this.upMaterial(this.group)
    }
  }
  disableClip() {
    this.enable = false
    if (this.group) {
      this.divider.style.display = 'none'

      this.group.traverse((object) => {
        if (object instanceof Mesh && object.material instanceof Material) {
          object.material.clippingPlanes = null
        }
      })
    }
  }
  private updatePlaneClip(px: number) {
    const rect = this.container.getBoundingClientRect()
    const xInContainer = Math.max(0, Math.min(rect.width, px))
    const cameraWidth = this.camera.right - this.camera.left

    // 比例映射到相机坐标
    const worldX = (xInContainer / rect.width) * cameraWidth + this.camera.left
    this.clipPlane.setFromNormalAndCoplanarPoint(new Vector3(-1, 0, 0), new Vector3(worldX, 0, 0))
  }
}
